package com.handpay.framework.swiper;

import android.content.Context;
import android.graphics.Bitmap;
import android.text.TextUtils;
import com.dynamicode.p27.lib.bluetooth4.DcBleDevice;
import com.dynamicode.p27.lib.inter.CSwiperController;
import com.dynamicode.p27.lib.inter.CSwiperStateChangedListener;
import com.handpay.framework.ClientEngine;
import com.handpay.framework.swiper.ic.IShowSelectApplication;
import com.handpay.framework.utils.ArithUtil;
import com.handpay.framework.utils.CommonUtils;
import com.handpay.zztong.hp.log.HPLog;
import com.handpay.zztong.hp.other.activity.ShowHtmlActivity;
import com.mset.cardswiper.Convert;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeoutException;

/*****
 * 动联P84蓝牙刷卡器
 */
public class DynamiCodeP84 extends AbstractBbposSwiper implements CSwiperStateChangedListener, IBusinessSwiper {

    private static String TAG = "DynamiCodeP84";
    private static int TRADETYPE_1 = 1;// 查询
    private static int TRADETYPE_2 = 2;// 消费

    private CSwiperController swiperController;
    private Context mContext;
    private String devAddress;
    public boolean mIsSwiperOK = false;
    private String mData = "";
    private IShowSelectApplication selectApplication;
    private SwipeTransData mSwipeTransData;
    private String swiperCSN;
    private String macStr;
    private String mAmount;
    private boolean isCancleOperation=false;
    public DynamiCodeP84(Context context, String address, IShowSelectApplication selectApplication) {

        devAddress = address;
        mContext = context;
        this.selectApplication = selectApplication;
        mLock = new AsynSwiperLock();
        mIsSwiperOK = true;
        initSDK();
    }

    public void initSDK() {
        try {
            if (swiperController == null) {
                HPLog.e(TAG, ">>>>ItronSwiper:initSdk<<<<" + swiperController);
                swiperController = new CSwiperController(mContext, this);
                HPLog.e(TAG, ">>>>ItronSwiper:initSdk<<<<" + swiperController);
            }
        } catch (Exception e) {
            HPLog.e(TAG, ">>>>ItronSwiper:initSdk :Exception<<<<" + e);
            e.printStackTrace();

        }

    }

    public boolean connect() {

        try {
            HPLog.e(TAG, "〈〈〈〈〈connect〉〉〉〉〉");
            swiperController.connectDevice(devAddress, 20);
        } catch (Exception e) {
            HPLog.i(TAG, "", e);
            HPLog.e(TAG, "〈〈〈〈〈connect〉〉〉〉〉Exception");
            mIsSwiperOK = false;
        }
        return mIsSwiperOK;
    }

    @Override
    public String getCSN() {
        HPLog.i(TAG, "getCSN()----");
        if (connect()) {

            if (swiperController != null) {
                // 获取设备信息
                swiperController.getDeviceInfo();

                try {
                    mLock.lock(20, AsynSwiperLock.GETCSN);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (swiperCSN != null) {
                HPLog.i(TAG, "getCSN----" + swiperCSN);
                return swiperCSN;
            }
        }
        return null;
    }

    @Override
    public boolean stopOperation() {
        HPLog.e(TAG, ">>>>stopOperation<<<<");
        mData = null;
        mHTData.clear();
        isCancleOperation=true;
        if (swiperController != null) {
            // 刷卡器发送指令,使刷卡器进入刷卡状态以后接受到该指令退出刷卡状态,进入IDLE状态
//            swiperController.stopScan();
            swiperController.stopCSwiper();
        }
        if(mLock!=null){
            mLock.unlock(AsynSwiperLock.IDLE);
        }
        return true;
    }

    @Override
    public boolean closeDevice() {
        HPLog.e(TAG, ">>>>closeDevice<<<<");
        stopOperation();
        mIsSwiperOK = false;
        mContext = null;
        selectApplication = null;
        if (swiperController != null) {
            // 删除控制器CSwiperController,释放资源
            swiperController.clearSwiperController();
            swiperController = null;
        }
        return true;
    }

    @Override
    public SwipeResult swipeCard(String factor, int timeout) {
        HPLog.i(TAG, "----swipeCard-----");
        isCancleOperation=false;
        if (swiperController == null) {
            HPLog.i(TAG, "swipeCard:swiperController is null");
            // 当取消处理
            return new SwipeResult(SwipeStatus.SWIPE_CANCEL);
        }
        initTransData(factor, timeout);
        //刷卡类型
        int TRADETYPE=TRADETYPE_2;
        String mount="0";
        if(!TextUtils.isEmpty(mAmount)){//消费业务
            HPLog.i(TAG, "P84--swipecard--mount:" + mAmount);
            mount = CommonUtils.formatAmount(mAmount);
            DecimalFormat decimalFormat = new DecimalFormat("###################.###########");
            String am = decimalFormat.format(ArithUtil.mul(Double.parseDouble(mount), 100d));
            HPLog.i(TAG, "P84--swipecard--am:" + am);
            mHTData.put(IBusinessSwiper.BANK_AMOUNT_KEY, am);
            HPLog.i(TAG, "P84--swipecard--mount:" + mount+",factor:"+factor);
        }else{//查询业务
            TRADETYPE=TRADETYPE_1;
        }
        //金额元为单位字符串
        swiperController.startSwiper(TRADETYPE, mount, factor, timeout);
        try {
            mLock.lock(timeout, AsynSwiperLock.NEW_SWIPE_CARD);
        } catch (TimeoutException te) {
            HPLog.i(TAG, "", te);
            return new SwipeResult(SwipeStatus.SWIPE_TIMEOUT);
        }
        HPLog.i(TAG,"---swipeCard--:isCancleOperation:"+isCancleOperation);
        if(isCancleOperation){
            isCancleOperation=false;
            mHTData.clear();
            mAmount=null;
            mData=null;
            return new SwipeResult(SwipeStatus.SWIPE_CANCEL, null);
        }
       String temp_cardType=mHTData.get("cardType");
        HPLog.i(TAG, "swipeCard---cardType:" +temp_cardType);
        String cardType = mHTData.get("DW_TRADE");
        if (!TextUtils.isEmpty(cardType)) {
            SwipeResult result = new SwipeResult(SwipeStatus.SWIPE_OK, null);
            result.mCardType = cardType;
            mHTData.remove("DW_TRADE");
            return result;
        }
        if (temp_cardType != null && (!temp_cardType.equals("01")&&!temp_cardType.equals("02"))) {
            // 磁条卡
            // 检查磁条刷卡所必备的数据
            if (null == mHTData.get(IBusinessSwiper.BANK_DYNAMIC_KEY)) {
                HPLog.e(TAG, "no dynamic key");
                return new SwipeResult(SwipeStatus.SWIPE_ERROR);
            }
            if (null == mHTData.get(IBusinessSwiper.BANK_TRACK2_KEY)) {
                HPLog.e(TAG, "no track2");
                return new SwipeResult(SwipeStatus.SWIPE_ERROR);
            }
            if (null == mHTData.get(IBusinessSwiper.BANK_PLAIN_ACCOUNT_KEY)) {
                HPLog.e(TAG, "no plain account");
                return new SwipeResult(SwipeStatus.SWIPE_ERROR);
            }
            SwipeResult result = new SwipeResult(SwipeStatus.SWIPE_OK, mHTData.get(IBusinessSwiper.BANK_PLAIN_ACCOUNT_KEY));
            result.mNeedInputPwd = false;
            result.mCardType = temp_cardType;
            return result;
        } else if (temp_cardType != null && (temp_cardType.equals("01")||temp_cardType.equals("02"))) {
            // IC卡
            mSwipeTransData.isIcTrans = true;
            mData = mHTData.get(IBusinessSwiper.BANK_PLAIN_ACCOUNT_KEY);

            if (null == swiperController) {
                HPLog.i(TAG, "bbpos cancel card");
                // 当取消处理
                return new SwipeResult(SwipeStatus.SWIPE_CANCEL);
            }
            if (TextUtils.isEmpty(mData)) {
                HPLog.i(TAG, "TextUtils.isEmpty(mData)");
                return new SwipeResult(SwipeStatus.SWIPE_ERROR);
            }
            SwipeResult result = new SwipeResult(SwipeStatus.SWIPE_OK, mData);
            result.mNeedInputPwd = false;
            return result;
            // return iccStartEmv();
        } else if (null == swiperController) {
            HPLog.i(TAG, "bbpos cancel card");
            // 当取消处理
            return new SwipeResult(SwipeStatus.SWIPE_CANCEL);
        } else {
            // 当做错误处理
            return new SwipeResult(SwipeStatus.SWIPE_ERROR);
        }
    }

    private void initTransData(String factor, int timeOut) {
        // mHTData，可以在后面完全被SwipeTransData取代
        mHTData.clear();
        mSwipeTransData = new SwipeTransData();
        mSwipeTransData.mBbposICTranIndex = 0;
        mSwipeTransData.mFactor = factor;
        mSwipeTransData.mTimeout = timeOut;
    }

    // 格式化数据 type=0:关键数据 type=1 mac数据
    public String formatData(String data, int type) {
        int len;
        StringBuffer sb = new StringBuffer();
        if (mSwiperMode == SwiperMode.SUPER_TRANS) {
            HPLog.e(TAG, "super");
            sb.append(Convert.bytesToHexString(data.getBytes()));
        } else {
            HPLog.e(TAG, "normal");
            sb.append(Convert.bytesToHexString(CommonUtils.hexStringToBytes(data)));
        }

        if (type == 0) {
            len = sb.length();
            while ((len % 16) > 0) {
                sb.append("00");
                len = sb.length();
            }
        } else if (type == 1) { // mac
            sb.append("80");
            len = sb.length();
            while ((len % 16) > 0) {
                sb.append("00");
                len = sb.length();
            }
            sb.append("8000000000000000");
        }
        return sb.toString();
    }

    @Override
    public String encData(String data, String index, String factor) {
        if (index.equals("13")) {
            float money = Float.parseFloat(data);
            if (money > 0) {
                HPLog.e(TAG, "我大于0了-----" + money);
            } else {
                HPLog.e(TAG, "我小于0了-----" + money);
            }
        }
        HPLog.e(TAG, "encData-data: " + data + " index: " + index);
        factor = factor.substring(0, factor.length() - 2);
        HPLog.e(TAG, factor);
        if (ISwiperListener.KeyDataIndex.equals(index)) {
            data = formatData(data, 0);
            // data = formatDataAdpu(data);
            HPLog.e(TAG, "encData-data: " + data);
            mData = swiperController.encryptData(data);
            HPLog.e(TAG, "加密后data:" + mData);
            return mData;
        } else if (PIN_INDEX.equals(index)) {

            mData = swiperController.encryptPin(data);
            HPLog.e(TAG, "加密后PIN:" + mData);
            return mData;
        } else if (ISwiperListener.MacDataIndex.equals(index)) {
            String macplain = null;
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            try {
                bos.write(String.valueOf(data.toCharArray()).getBytes());
                bos.write(0x80);
                while (bos.size() % 8 != 0) {
                    bos.write(0x00);
                }
                bos.write(0x80);
                for (int i = 0; i < 7; i++) {
                    bos.write(0x00);
                }
                byte[] macPlainBytes = bos.toByteArray();
                macplain = CommonUtils.bytesToHexString(macPlainBytes);
            } catch (IOException ioe) {
                HPLog.e(TAG, "", ioe);
                try {
                    bos.close();
                } catch (IOException e) {
                    HPLog.e(TAG, "", e);
                }
            }
            HPLog.e(TAG, "加密前Mac:" + macplain);
            // CommandReturn commandReturn = itcommm.Get_MAC(0,
            // 1,Util.HexToBin(factor), Util.HexToBin(macplain));
            macStr = swiperController.calcMac(macplain, factor);
            HPLog.e(TAG, "加密后Mac:" + macStr);
            return macStr;
        }
        return null;
    }

    @Override
    public Hashtable<String, String> batchEncData(Hashtable<Integer, String> htDatas, String factor) {
        return null;
    }

    @Override
    public boolean isSwiperReady() {
        return mIsSwiperOK;
    }

    @Override
    public SwiperModel getSwiperModel() {
        return SwiperModel.P84_BLUETOOTH;
    }

    @Override
    public void onCardSwipeDetected() {
        HPLog.i(TAG, "onCardSwipeDetected");
    }

    @Override
    public void onDeviceConnected() {
        HPLog.i(TAG, "onDeviceConnected");
        // 连接刷卡器回调
        swiperController.getDeviceInfo();
    }

    @Override
    public void onDeviceConnectedFailed() {
        HPLog.i(TAG, "onDeviceConnectedFailed---连接失败");

    }

    @Override
    public void onDeviceDisconnected() {
        HPLog.i(TAG, "onDeviceDisconnected---销毁刷卡器");
        stopOperation();
        mIsSwiperOK = false;
        mContext = null;
        selectApplication = null;
        if (swiperController != null) {
            // 删除控制器CSwiperController,释放资源
            swiperController.clearSwiperController();
            swiperController = null;
        }
    }

    @Override
    public void onDeviceListRefresh(List<DcBleDevice> arg0) {
        HPLog.i(TAG, "onDeviceListRefresh---" + arg0);
    }

    @Override
    public void onDeviceScanStopped() {
        HPLog.i(TAG, "onDeviceScanStopped");
    }

    @Override
    public void onDeviceScanning() {
        HPLog.i(TAG, "onDeviceScanning");
    }

    @Override
    public void onError(int arg0) {
        HPLog.i(TAG, "onError" + arg0);
        mData = null;
        mAmount=null;
        if (mLock != null) {
            mLock.unlock(AsynSwiperLock.IDLE);
        }
    }

    @Override
    public void onNeedInsertICCard() {
        HPLog.i(TAG, "onNeedInsertICCard");
        mHTData.put("DW_TRADE", "2");
        mLock.unlock(AsynSwiperLock.NEW_SWIPE_CARD);
    }

    @Override
    public void onReturnPinBlock(String s) {
        HPLog.i(TAG,"----onReturnPinBlock-----s:"+s);
        mHTData.put(IBusinessSwiper.BANK_PAN_KEY, s);
        mLock.unlock(AsynSwiperLock.NEW_INPUT_PWD);
    }
    //if cancle current swipe or cancle input password
    @Override
    public void onPressCancleKey() {
        HPLog.i(TAG,"---key---onPressCancleKey---");
        isCancleOperation=true;
        mLock.unlock(AsynSwiperLock.IDLE);
    }

    @Override
    public void onReturnCardInfo(Map<String, String> cardInfos) {
        String isIC = cardInfos.get(CSwiperController.DCSWIPER_RETURN_MAP_KEY_ICCARDFLAG);
        HPLog.e(TAG, "isIC:" + isIC);
        /**
         * isIC
         * 01为IC
           02为非接
         */
        if (isIC != null && (isIC.equals("01") || isIC.equals("02"))) {
            mHTData.put("cardType", cardInfos.get(CSwiperController.DCSWIPER_RETURN_MAP_KEY_ICCARDFLAG));
            mHTData.put(IBusinessSwiper.BANK_PLAIN_ACCOUNT_KEY, cardInfos.get(CSwiperController.DCSWIPER_RETURN_MAP_KEY_ACCOUNT1));
            mHTData.put(IBusinessSwiper.BANK_DYNAMIC_KEY, cardInfos.get(CSwiperController.DCSWIPER_RETURN_MAP_KEY_RAMDOM));
            mHTData.put(IBusinessSwiper.BANK_PLAIN_EXPIRE_DATE, cardInfos.get(CSwiperController.DCSWIPER_RETURN_MAP_KEY_EXPIRED));
            mHTData.put(IBusinessSwiper.BANK_TRACK2_KEY, cardInfos.get(CSwiperController.DCSWIPER_RETURN_MAP_KEY_TRACK2));
            String IcNumber = cardInfos.get(CSwiperController.DCSWIPER_RETURN_MAP_KEY_CRDSQN);
            String DcData = cardInfos.get(CSwiperController.DCSWIPER_RETURN_MAP_KEY_ICDATA);
            if (IcNumber != null && DcData != null) {
                mHTData.put(IBusinessSwiper.BANK_ICNUMBER, IcNumber);
                mHTData.put(IBusinessSwiper.BANK_DCDATA, DcData);
            }
        } else {
            //磁条卡
            mHTData.put("cardType", cardInfos.get(CSwiperController.DCSWIPER_RETURN_MAP_KEY_ICCARDFLAG));
            mHTData.put(IBusinessSwiper.BANK_PLAIN_ACCOUNT_KEY, cardInfos.get(CSwiperController.DCSWIPER_RETURN_MAP_KEY_ACCOUNT1));
            mHTData.put(IBusinessSwiper.BANK_TRACK2_KEY, cardInfos.get(CSwiperController.DCSWIPER_RETURN_MAP_KEY_TRACK2));
            mHTData.put(IBusinessSwiper.BANK_DYNAMIC_KEY, cardInfos.get(CSwiperController.DCSWIPER_RETURN_MAP_KEY_RAMDOM));
            mHTData.put(IBusinessSwiper.BANK_PLAIN_EXPIRE_DATE, cardInfos.get(CSwiperController.DCSWIPER_RETURN_MAP_KEY_EXPIRED));
        }
        HPLog.i(TAG, "onReturnCardInfo" + mHTData);
        //get plainblock notify swiper
        mLock.unlock(AsynSwiperLock.NEW_SWIPE_CARD);
    }

    @Override
    public void onReturnDeviceInfo(Map<String, String> deviceInfos) {
        HPLog.e(TAG, "onReturnDeviceInfo" + deviceInfos.get("KSN"));
        swiperCSN = deviceInfos.get("KSN");
        mLock.unlock(AsynSwiperLock.GETCSN);
    }

    @Override
    public void onTimeout() {
        HPLog.i(TAG, "onTimeout");
    }

    @Override
    public void onWaitingForCardSwipe() {
        HPLog.i(TAG, "onWaitingForCardSwipe");
    }

    @Override
    public void onWaitingForDevice() {
        HPLog.i(TAG, "onWaitingForDevice");
    }

    @Override
    public IBusinessSwiper.Result affirmAmount(String amount, int timeout) {
        this.mAmount = amount;
        HPLog.i(TAG, "P84---mAmount:" + mAmount);
        return IBusinessSwiper.Result.OK;
    }

    @Override
    public Hashtable<String, String> getBankInfo() {
        Hashtable<String, String> result = (Hashtable<String, String>) mHTData.clone();
        mHTData.clear();
        return result;
    }

    @Override
    public Result inputPwd(String factor, int timeout) {
        isCancleOperation=false;
        if(swiperController!=null)
            swiperController.getPinBlock(60);
        try {
            mLock.lock(timeout, AsynSwiperLock.NEW_INPUT_PWD);
        } catch (TimeoutException te) {
            HPLog.i(TAG, "", te);
            return Result.ERROR;
        }
        if(isCancleOperation){
            isCancleOperation=false;
            mHTData.clear();
            mAmount=null;
            mData=null;
            return Result.CANCEL;
        }
        if (!TextUtils.isEmpty(mAmount)) {
            HPLog.i(TAG, "enc amount:" + mAmount);
            String encAmount;
            encAmount = encData(mAmount, ISwiperListener.KeyDataIndex, factor);
            HPLog.i(TAG, "enc amount result:" + encAmount);
            if (!TextUtils.isEmpty(encAmount)) {
                mHTData.put(BANK_AMOUNT_KEY, encAmount);
            } else {
                return Result.ERROR;
            }
        }
        if (null == mHTData.get(BANK_ACCOUNT_KEY)) {
            String plainAccount = mHTData.get(BANK_PLAIN_ACCOUNT_KEY);
            if (null != plainAccount) {
                HPLog.i(TAG, "enc account:" + plainAccount + " mSwiperMode:" + mSwiperMode);
                String encAccount;
                if (mSwiperMode == SwiperMode.NORMAL_TRANS) {
                    encAccount = encData(CommonUtils.string2Hex(plainAccount), ISwiperListener.KeyDataIndex, factor);
                } else {
                    encAccount = encData(plainAccount, ISwiperListener.KeyDataIndex, factor);
                }
                HPLog.i(TAG, "enc account result:" + encAccount);
                if (!TextUtils.isEmpty(encAccount)) {
                    mHTData.put(BANK_ACCOUNT_KEY, encAccount);
                    if (ClientEngine.getInstance().getGlobal(BANK_TransactionType_KEY) != null
                            && ClientEngine.getInstance().getGlobal(BANK_TransactionType_KEY).equals("PurchaseAdvice")) {
                        String merchantId = encData(ShowHtmlActivity.map.get("merchantId"), ISwiperListener.KeyDataIndex, factor);
                        String orderId = encData(ShowHtmlActivity.map.get("orderId"), ISwiperListener.KeyDataIndex, factor);
                        String terminalId = encData(ShowHtmlActivity.map.get("terminalId"), ISwiperListener.KeyDataIndex, factor);
                        String transAmount = encData(CommonUtils.formatMoenyToUnionpay(ShowHtmlActivity.map.get("transAmount")), ISwiperListener.KeyDataIndex, factor);
                        HPLog.e("merchantId", merchantId);
                        HPLog.e("orderId", orderId);
                        HPLog.e("terminalId", terminalId);
                        HPLog.e("transAmount", transAmount);
                        // 先保存为全局变量,备用
                        ClientEngine.getInstance().saveGlobal(BANK_MerchantID_KEY, merchantId);
                        ClientEngine.getInstance().saveGlobal(BANK_OrderID_KEY, orderId);
                        ClientEngine.getInstance().saveGlobal(BANK_TerminalID_KEY, terminalId);
                        ClientEngine.getInstance().saveGlobal(BANK_TransAmount_KEY, transAmount);
                        mHTData.put(BANK_MerchantID_KEY, merchantId);
                        mHTData.put(BANK_OrderID_KEY, orderId);
                        mHTData.put(BANK_TerminalID_KEY, terminalId);
                        mHTData.put(BANK_TransAmount_KEY, transAmount);
                    }
                } else {
                    HPLog.i(TAG, "enc account error!");
                    return Result.ERROR;
                }
            } else {
                HPLog.e(TAG, "no enc account and no plain account! error");
                return Result.ERROR;
            }
        }
        HPLog.i(HPLog.TAG_RESULT, "end with inputpwd");
        mAmount=null;
        mData=null;
        return Result.OK;
    }
    @Override
    public SwipeResult registerPwd(String factor, int timeout) {
        return null;
    }

    @Override
    public boolean printBitMap(int position, Bitmap bitmap) {
        return false;
    }

    @Override
    public boolean printString(String data) {
        return false;
    }

    @Override
    public boolean print(String data, Bitmap bitmap) {
        return false;
    }

    @Override
    public void setPlainPwd(String pwd) {

    }


}
